import java.util.HashSet;
import java.util.Set;


/**
 * 
 * @author "Cunxin Jia"
 *
 */
public class GOLEM {
	private Background background;
	private Foreground foreground;
	
	public GOLEM(Background background, Foreground foreground) {
		this.background = background;
		this.foreground = foreground;
	}
	
	public void learn() {
		int bestCovered = 0;
		Clause bestRLGG;
		Set<Literal> S = new HashSet<Literal>();
		int i = 0;
		Literal bestPos1 = null;
		Literal bestPos2 = null;
		Set<Literal> coveredPosSet = null;
		
		/**
		 * Randomly select s pairs of positive examples
		 * construct rlgg(S) for each pair S and select the pair S_best that covers
		 * the most positive examples
		 */
		while(i < Param.s) {
			Literal pos1 = foreground.randomSelectPos();
			Literal pos2 = foreground.randomSelectPos();
			Clause rlgg = background.RLGG(pos1, pos2);
			System.out.println(pos1.toString());
			System.out.println(pos2.toString());
			System.out.println(rlgg.toString());
			VarFactory.getInstance().printAll();
			int covered = background.getCoveredNum(rlgg, foreground.getPosSet());
			if(covered > bestCovered) {
				bestCovered = covered;
				bestRLGG = rlgg;
				System.out.println(rlgg.toString());
				bestPos1 = pos1;
				bestPos2 = pos2;
				coveredPosSet = background.getCoveredSet(rlgg, foreground.getPosSet());
			}

			
			i++;
		}
		S.add(bestPos1);
		S.add(bestPos2);
		foreground.removeCoveredPos(coveredPosSet);
		/**
		 * Iteratively construct rlgg while the number of covered positive examples increases
		 */
		int formerCoveredNum = 0;
		while(foreground.getPosSet().size() != 0) {
			i = 0;
			Set<Literal> tmpS = S;
			formerCoveredNum = bestCovered;
			bestCovered = 0;
			
			while(i < Param.s) {
				Literal pos = foreground.randomSelectPos();
				tmpS.add(pos);
				Clause rlgg = background.RLGG(tmpS);
				int covered = background.getCoveredNum(rlgg, foreground.getPosSet());
				if(covered > bestCovered) {
					bestRLGG = rlgg;
					System.out.println(rlgg.toString());
					bestCovered = covered;
					S = tmpS;
					coveredPosSet = background.getCoveredSet(rlgg, foreground.getPosSet());
				}
			}
			foreground.removeCoveredPos(coveredPosSet);
			if(bestCovered <= formerCoveredNum) {
				break;
			}
		}
		
			
	}
	
	
	
	public static void main(String[] args) {
//		String clauseString1 = "gd(kate,tom) :- father(tom,jerry),daughter(kate,jerry),father(jack,penny),daughter(susan,penny).";
//		String clauseString2 = "gd(susan,jack) :- father(tom,jerry),daughter(kate,jerry),father(jack,penny),daughter(susan,penny).";
//		Clause clause1 = new Clause(clauseString1);
//		Clause clause2 = new Clause(clauseString2);
//		Clause lggClause = LGG.generateLGG(clause1, clause2);
//		System.out.println(lggClause.toString());
//		VarFactory.getInstance().printAll();
		
		
		
		Set<Literal> posSet = new HashSet<Literal>();
			posSet.add(new Literal("daughter(d1,f1)"));
			posSet.add(new Literal("daughter(d2,f2)"));
			posSet.add(new Literal("daughter(d3,f3)"));
			posSet.add(new Literal("daughter(d4,f4)"));
			posSet.add(new Literal("daughter(d5,f5)"));
			posSet.add(new Literal("daughter(d6,f6)"));
			
		
		Set<Literal> negSet = new HashSet<Literal>();
			negSet.add(new Literal("daughter(f3,d3)"));
		
		Set<Literal> background = new HashSet<Literal>();
			background.add(new Literal("female(d1)"));
			background.add(new Literal("female(d2)"));
			background.add(new Literal("female(d3)"));
			background.add(new Literal("female(d4)"));
			background.add(new Literal("female(d5)"));
			background.add(new Literal("female(d6)"));
			background.add(new Literal("parent(f1,d1)"));
			background.add(new Literal("parent(f2,d2)"));
			background.add(new Literal("parent(f3,d3)"));
			background.add(new Literal("parent(f4,d4)"));
			background.add(new Literal("parent(f5,d5)"));
			background.add(new Literal("parent(f6,d6)"));
			
			
		Background bkg = new Background(background);
		Foreground frg = new Foreground(posSet, negSet);
	
		GOLEM golem = new GOLEM(bkg, frg);
		golem.learn();
		
//		Clause clause = new Clause("daughter(X,Y):-female(X),parent(Y,X).");
		

		
//		for(int i = 0; i < 20; i++) {
//			Literal lit = frg.randomSelectPos();
//			if(lit != null)
//				System.out.println(lit.toString());
//		}
//		
//		
//		Set<Literal> covered = bkg.getCoveredSet(clause, posSet);
//		Iterator<Literal> iter = covered.iterator();
//		while(iter.hasNext()) {
//			System.out.println(iter.next().toString());
//		}
		

	}
}
